/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.specific.sge.status;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;

import jp.aist.gtrc.plus.scheduler.node.NodeResource;
import jp.aist.gtrc.plus.scheduler.specific.sge.status.SGEComplexEntry.RelationOpe;
import jp.aist.gtrc.plus.scheduler.status.ArchType;
import jp.aist.gtrc.plus.scheduler.status.OSType;

public class SGEArch {

	private static class SGEOSArch {

		private final OSType os;
		private final ArchType arch;

		SGEOSArch(OSType os, ArchType arch) {
			assert(os != null);
			assert(arch != null);
			this.os = os;
			this.arch = arch;
		}
		OSType getOSType() {
			return os;
		}
		ArchType getArchType() {
			return arch;
		}

		public String toString() {
			return os.toString() + "-" + arch.toString();
		}

	}

	private static final HashMap<String, OSType> osMap;
	private static final HashMap<String, ArchType> archMap;
	private static final Collection<OSType> unknownOS;
	private static final Collection<ArchType> unknownArch;
	private static final Map<String, SGEOSArch> supportedArchList;

	static {

		osMap = new HashMap<String, OSType>();
		osMap.put("lx22", OSType.Linux_22);
		osMap.put("lx24", OSType.Linux_24);
		osMap.put("lx26", OSType.Linux_26);
		osMap.put("sol", OSType.Solaris);
		osMap.put("win32", OSType.Windows);
		//osMap.put("nbsd", OSType.NetBSD);
		//osMap.put("fbsd", OSType.FreeBSD);
		//osMap.put("hp11", OSType.HPUX_11);

		unknownOS = new LinkedList<OSType>();
		unknownOS.add(OSType.Unknown);

		archMap = new HashMap<String, ArchType>();
		archMap.put("x86", ArchType.x86);
		archMap.put("ia64", ArchType.ia64);
		archMap.put("amd64", ArchType.x86_64);
		archMap.put("x86_64", ArchType.x86_64);
		archMap.put("sparc", ArchType.sparc);
		archMap.put("sparc64", ArchType.sparc64);
		archMap.put("alpha", ArchType.alpha);
		archMap.put("ppc", ArchType.ppc);

		unknownArch = new LinkedList<ArchType>();
		unknownArch.add(ArchType.unknown);

		supportedArchList = new LinkedHashMap<String, SGEOSArch>();
		addSupportArch("lx22-x86");
		addSupportArch("lx22-sparc");
		addSupportArch("lx22-alpha");

		addSupportArch("lx24-x86");
		addSupportArch("lx24-ia64");
		addSupportArch("lx24-sparc");
		addSupportArch("lx24-alpha");
		addSupportArch("lx24-amd64");

		addSupportArch("lx26-x86");
		addSupportArch("lx26-ia64");
		addSupportArch("lx26-amd64");
		addSupportArch("lx26-alpha");
		addSupportArch("lx26-ppc");
		addSupportArch("lx26-sparc");

		addSupportArch("sol-x86");
		addSupportArch("sol-amd64");
		addSupportArch("sol-sparc");
		addSupportArch("sol-sparc64");

		addSupportArch("win32-x86");

	}

	private static void addSupportArch(String archName) {

		String[] s = archName.split("-");
		assert(s.length == 2);
		OSType os = osMap.get(s[0]);
		ArchType arch = archMap.get(s[1]);
		assert(os != null);
		assert(arch != null);
		supportedArchList.put(archName, new SGEOSArch(os, arch));

	}

	public static OSType getOSType(String arch) {

		SGEOSArch osa = supportedArchList.get(arch);
		return (osa != null) ? osa.getOSType() : OSType.Unknown;

	}

	public static ArchType getArchType(String arch) {

		SGEOSArch osa = supportedArchList.get(arch);
		return (osa != null) ? osa.getArchType() : ArchType.unknown;

	}

	public static Collection<NodeResource> getMacthedNodeResources(
			String arch, int cpuNum, int procNum) {

		// NOTE: 'arch' is normal text or regular expresion
		LinkedList<NodeResource> list = new LinkedList<NodeResource>();
		for (Map.Entry<String, SGEOSArch> ent: supportedArchList.entrySet()) {
			if (SGEComplex.compareREString(RelationOpe.EQ, arch, ent.getKey())) {
				SGEOSArch osa = ent.getValue();
				NodeResource rsc = new NodeResource(cpuNum, procNum,
						osa.getArchType(), osa.getOSType());
				list.add(rsc);
			}
		}

		return list;

	}

}
